#include <rtdevice.h>
#include <rtthread.h>
#include <board.h>
#include <dev_spi_flash.h>
#include <drv_spi.h>
#include "dev_spi_flash_sfud.h"
#include <dfs_fs.h>

// #define DBG_TAG "app.port_spi_flash"
// #define DBG_LVL DBG_INFO
// #include <rtdbg.h>

#define SPI_BUS_NAME "spi2"
#define SPI_DEVICE_NAME "spi20"
#define SPI_FLASH_DEVICE_NAME "W25Q64S"

#define SPI_FLASH_CS_PIN    GET_PIN(B, 12)   // CS=PB12
int spi_flash_init(void)
{
    /* 挂载SPI Flash设备到软SPI1总线 */
    if (rt_hw_spi_device_attach(SPI_BUS_NAME, SPI_DEVICE_NAME, SPI_FLASH_CS_PIN) != RT_EOK)
    {
        rt_kprintf("Failed to attach SPI Flash!\n");
        return -RT_ERROR;
    }    
  
    if (RT_NULL == rt_sfud_flash_probe(SPI_FLASH_DEVICE_NAME, SPI_DEVICE_NAME))
    {
        return -RT_ERROR;
    };

    /* 挂载文件系统 */
    #ifdef BSP_SPI_FLASH_MOUNT_FATFS
    if (dfs_mount(SPI_FLASH_DEVICE_NAME, "/spi", "elm", 0, 0) != 0)
    {
        LOG_W("mount to '/spi' failed! try to mkfs %s", SPI_FLASH_DEVICE_NAME);
        dfs_mkfs("elm", SPI_FLASH_DEVICE_NAME);
        if (dfs_mount(SPI_FLASH_DEVICE_NAME, "/spi", "elm", 0, 0) == 0)
        {
            LOG_I("mount to '/spi' success!");
            goto _exit;
        }
    }
    LOG_I("mount to '/spi' success!");
    #endif

_exit:
    return 0;
}
INIT_APP_EXPORT(spi_flash_init);


static void spi_flash_test(int argc, char **argv)
{
    rt_uint32_t id;
    rt_uint8_t buf[256];
    rt_uint8_t test_buf[256];
    struct rt_spi_device * dev = (struct rt_spi_device *)rt_device_find(SPI_DEVICE_NAME);
    
    if (!dev)
    {
        rt_kprintf("Find SPI device failed!\n");
        return;
    }

    struct rt_spi_configuration cfg;
    cfg.mode = RT_SPI_MODE_0 | RT_SPI_MSB; // 模式0, MSB first
    cfg.data_width = 8;
    cfg.max_hz = 1 * 1000 * 1000; // 1MHz
    rt_spi_configure(dev, &cfg);
    
    /* 读取ID */
    rt_spi_send_then_recv(dev, (rt_uint8_t[4]){0x9F}, 1, (rt_uint8_t *)&id, 3);
    rt_kprintf("Flash ID: 0x%06X\n", id);

    if(argc==1) return; /*used for read id only*/
    
    /* 擦除测试扇区 */
    rt_kprintf("Erasing sector at 0x000000...\n");
    rt_spi_send(dev, (rt_uint8_t[]){0x06}, 1); // WREN
    rt_spi_send(dev, (rt_uint8_t[]){0x20, 0x00, 0x00, 0x00}, 4); // Sector Erase
    rt_thread_mdelay(100); // Wait for erase completion
    
    rt_kprintf("Erase completed\n");
    
    /* 测试写入 */
    rt_memset(test_buf, 0x5A, sizeof(test_buf));
    rt_kprintf("Writing test data...\n");
    rt_spi_send(dev, (rt_uint8_t[]){0x06}, 1); // WREN
    rt_spi_send_then_send(dev, (rt_uint8_t[]){0x02, 0x00, 0x00, 0x00}, 4, test_buf, sizeof(test_buf));
    rt_thread_mdelay(10); // Wait for write completion
    
    rt_kprintf("Write completed\n");
    
    /* 读取验证 */
    rt_memset(buf, 0, sizeof(buf));
    rt_kprintf("Reading back data...\n");
    rt_spi_send_then_recv(dev, (rt_uint8_t[]){0x03, 0x00, 0x00, 0x00}, 4, buf, sizeof(buf));
    
    /* 验证数据 */
    if (rt_memcmp(test_buf, buf, sizeof(test_buf)) == 0)
    {
        rt_kprintf("SPI Flash test success!\n");
    }
    else
    {
        rt_kprintf("SPI Flash test failed!\n");
        rt_kprintf("Expected: ");
        for(int i=0; i<16; i++) rt_kprintf("%02X ", test_buf[i]);
        rt_kprintf("\nActual:   ");
        for(int i=0; i<16; i++) rt_kprintf("%02X ", buf[i]);
        rt_kprintf("\n");
    }
}
MSH_CMD_EXPORT(spi_flash_test, spi_flash_test!);